/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Dimensions, EventSubscription, Platform } from 'react-native';
import LayoutModule from '../turbo/NativeBreakPointsModule';
import { Breakpoints, WidthBreakpoint, HeightBreakpoint } from '../config/breakpoints/types';
import { widthBreakpoints, heightBreakpoints, widthBreakpointsMap, heightBreakpointsMap } from '../config/breakpoints/breakpoints';

const platform = Platform.OS as string;
const apiVersion = LayoutModule?.getApiVersion();
const deviceApiVersion = LayoutModule?.getDeviceApiVersion();
let canUseOpenHarmonyModule: boolean = false;
if (platform === 'harmony' && apiVersion && apiVersion >= 13 && deviceApiVersion && deviceApiVersion >= 13) {
  canUseOpenHarmonyModule = true;
}

export class BreakpointManager {
  private static instance: BreakpointManager;

  // 当前的横向断点
  private currentWidthBreakpoint: WidthBreakpoint = 'xs';

  // 当前的纵向断点
  private currentHeightBreakpoint: HeightBreakpoint = 'sm';

  // 存储回调函数
  private callbacks: Set<(widthBreakpoints: string, heightBreakpoints: string) => void> = new Set();

  // Dimensions事件监听ID
  private dimensionsListenerId: EventSubscription | null = null;

  private constructor() {
    this.updateBreakpoint = this.updateBreakpoint.bind(this);
    this.startListening();
  }

  // 获取 BreakpointManager 的单例
  public static getInstance(): BreakpointManager {
    if (!BreakpointManager.instance) {
      BreakpointManager.instance = new BreakpointManager();
    }
    return BreakpointManager.instance;
  }

  // 获取当前的横向断点
  public getCurrentWidthBreakpoint(): string {
    return this.currentWidthBreakpoint;
  }

  // 获取当前的纵向断点
  public getCurrentHeightBreakpoint(): string {
    return this.currentHeightBreakpoint;
  }

  // 更新当前的宽度断点和高度断点
  public updateBreakpoint(): void {
    // 更新横向断点
    let newWidthBreakpoint: WidthBreakpoint = 'xs'; // 默认值

    // 更新纵向断点
    let newHeightBreakpoint: HeightBreakpoint = 'sm'; // 默认值

    let widthBreakpointIndex: number | undefined;
    let heightBreakpointIndex: number | undefined;

    if (canUseOpenHarmonyModule) {
      widthBreakpointIndex = LayoutModule?.getWindowWidthBreakpoint();
      heightBreakpointIndex = LayoutModule?.getWindowHeightBreakpoint();
    }

    if (
      widthBreakpointIndex !== undefined &&
      heightBreakpointIndex !== undefined &&
      widthBreakpointIndex >= 0 &&
      widthBreakpointIndex < widthBreakpoints.length &&
      heightBreakpointIndex >= 0 &&
      heightBreakpointIndex < heightBreakpoints.length
    ) {
      console.debug('updateBreakpoint: use openharmony');
      newWidthBreakpoint = widthBreakpoints[widthBreakpointIndex];
      newHeightBreakpoint = heightBreakpoints[heightBreakpointIndex];
    } else {
      console.debug('updateBreakpoint: use mediaQuery');
      const { width, height } = Dimensions.get('window');
      newWidthBreakpoint = this.calculateBreakpoint(width, widthBreakpointsMap) as WidthBreakpoint;

      const aspectRatio = height / width;
      newHeightBreakpoint = this.calculateBreakpoint(aspectRatio, heightBreakpointsMap) as HeightBreakpoint;
    }

    // 仅在断点变化时更新
    if (this.currentWidthBreakpoint !== newWidthBreakpoint || this.currentHeightBreakpoint !== newHeightBreakpoint) {
      this.currentWidthBreakpoint = newWidthBreakpoint;
      this.currentHeightBreakpoint = newHeightBreakpoint;
      this.notifyCallbacks();
    }
  }

  // 计算断点
  public calculateBreakpoint(value: number, breakpoints: Breakpoints): string {
    for (const breakpoint in breakpoints) {
      if (value < breakpoints[breakpoint]) {
        return breakpoint; // 返回匹配的断点
      }
    }
    // 如果没有匹配的断点，返回第一个断点
    return Object.keys(breakpoints)[0];
  }

  // 通知所有回调函数
  private notifyCallbacks(): void {
    this.callbacks.forEach(callback => callback(this.currentWidthBreakpoint, this.currentHeightBreakpoint));
  }

  // 订阅断点变化
  public subscribeToBreakpoint(callback: (widthBreakpoints: string, heightBreakpoints: string) => void): () => void {
    this.callbacks.add(callback);
    return () => {
      this.callbacks.delete(callback);
    };
  }

  private startListening(): void {
    this.dimensionsListenerId = Dimensions.addEventListener('change', this.updateBreakpoint);
    this.updateBreakpoint();
  }

  public destroy(): void {
    if (this.dimensionsListenerId) {
      // 通过注销监听来避免内存泄漏
      this.dimensionsListenerId.remove();
      this.dimensionsListenerId = null;
    }
    this.callbacks.clear();
  }
}
